/*Test Distrubition Server. Copyright (C) 2007-2008 Cameron de Witte. (cameron.dewitte@gmail.com)
* 
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public 
* License as published by the Free Software Foundation, either version 3 of the License, or any later version. 
* 
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied 
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
* 
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public 
* License along with this program. If not, see http://www.gnu.org/licenses/.
*
* This file also partially written by Nigel Thorne (http://www.nigelthorne.com/blog/)
*/

using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace TestDistrubitionServer
{
    public class TcpServer
    {
        private readonly IMainForm iFrm;
        private readonly int port;
        private readonly List<Socket> sockets = new List<Socket>();
        private readonly List<Thread> threads = new List<Thread>();
        private bool running;

        public TcpServer(int port, IMainForm iFrm)
        {
            this.port = port;
            this.iFrm = iFrm;
        }

        public void Stop()
        {
            running = false;
            iFrm.AddLine("Server is stopping.\r\nKilling all clients......");
            foreach (Socket socket in sockets)
            {
                socket.Close();
            }
        }

        public void Run()
        {
            running = true;
            TcpListener tcpListener = new TcpListener(IPAddress.Any, port);
            iFrm.AddLine("The server has been started.");
            tcpListener.Start();

            while (running)
            {
                if (tcpListener.Pending())
                {
                    Socket socketForClient = NewSocket(tcpListener);
                    StartSocketHandler(socketForClient);
                }
                Thread.Sleep(10);
            }
        }

        private Socket NewSocket(TcpListener tcpListener)
        {
            Socket socketForClient = tcpListener.AcceptSocket();
            sockets.Add(socketForClient);
            return socketForClient;
        }

        private void StartSocketHandler(Socket socketForClient)
        {
            Thread thread = new Thread(new ThreadStart(delegate
                                                           {
                                                               SocketServer server =
                                                                   new SocketServer(socketForClient, iFrm);
                                                               server.ServeSocket();
                                                           }));
            threads.Add(thread);
            thread.Start();
        }
    }
}